﻿namespace VIT.BusinessLogicLayer
{
    using System;
    using System.Linq;
    using System.Collections.Generic;

    using VIT.DataAccessLayer;
    using VIT.DataTransferObjects.Presentation;
    using VIT.Entity;
    using VIT.Library;
    using VIT.Library.Web;
using System.Net.Mail;
using VIT.DataTransferObjects;

    public class ProductBLL : BLLBase
    {
        private readonly ICategoryLanguageDAL _categoryLanguageDAL;
        private readonly ICategoryDAL _categoryDAL;
        private readonly IProductTypeDAL _productTypeDAL;
        private readonly IProductManufacturerDAL _manufacturerDAL;
        private readonly IProductPriceDAL _productPriceDAL;
        private readonly IProductDAL _productDAL;
        private readonly IProductLanguageDAL _productLanguageDAL;
        private readonly IItemImageDAL _productImageDAL;
        private readonly IOrderDAL _orderDAL;
        private readonly IOrderProductDAL _orderProductDAL;

        private readonly string _domainStore;
        private readonly string _imageProductImagePath;
        private readonly string _imageItemThumbPath;
        private readonly string _imageItemDetailPath;

        private readonly URL _url;

        #region Constructor

        public ProductBLL(string connectionString = "")
            : base(connectionString)
        {
            this._categoryLanguageDAL = new CategoryLanguageDAL(DatabaseFactory);
            this._productLanguageDAL = new ProductLanguageDAL(DatabaseFactory);
            this._productImageDAL = new ItemImageDAL(DatabaseFactory);
            this._productDAL = new ProductDAL(this.DatabaseFactory);
            this._manufacturerDAL = new ProductManufacturerDAL(this.DatabaseFactory);
            this._categoryDAL = new CategoryDAL(this.DatabaseFactory);
            this._orderDAL = new OrderDAL(this.DatabaseFactory);
            this._orderProductDAL = new OrderProductDAL(this.DatabaseFactory);
            this._productTypeDAL = new ProductTypeDAL(this.DatabaseFactory);
            this._productPriceDAL = new ProductPriceDAL(this.DatabaseFactory);

            this._domainStore = SettingsManager.AppSettings.DomainStore;
            this._imageProductImagePath = SettingsManager.Constants.LinkProductImage;
            this._imageItemDetailPath = SettingsManager.Constants.LinkItemDetailImage;
            this._imageItemThumbPath = SettingsManager.Constants.LinkItemThumbImage;

            this._url = new URL();
        }
        #endregion

        #region public method
        public List<DataSimpleDto> SearchDataSimple(int companyId, string languageId, string key, out int totalPage, int Skip = 0, int Take = 0)
        {
            var query = this._productLanguageDAL.GetAll()
                .Where(e => e.Product.Item.CompanyId == companyId && e.LanguageId == languageId && e.Product.Item.IsPublished && !e.Product.Item.HasDeleted)
                .Where(e => e.Title.Contains(key) || e.Brief.Contains(key));

            var selected = query.OrderBy(e => e.Product.Item.Orders)
                .ThenByDescending(e => e.Product.Item.CreateDate)
                .Select(a => new DataSimpleDto
                {
                    Id = a.ProductId,
                    CategoryId = a.Product.CategoryId,
                    Title = a.Title,
                    Description = a.Brief,
                    ImagePath = a.Product.Image
                });

            totalPage = selected.Count();
            if (Skip > 0) selected = selected.Skip(Skip);
            if (Take > 0) selected = selected.Take(Take);

            var data = selected.ToList();

            var imagePathThumb = string.Format(this._imageProductImagePath, companyId);
            foreach (var item in data)
            {
                item.ImagePath = this._url.VirtualPath(imagePathThumb + item.ImagePath);
            }

            return data;
        }

        public List<ProductsDto> SearchProduct(int companyId, string languageId, string key, decimal fromPrice, decimal toPrice, out int totalPage, int Skip = 0, int Take = 0)
        {
            var query = this._productLanguageDAL.GetAll()
                .Where(e => e.Product.Item.CompanyId == companyId && e.LanguageId == languageId && e.Product.Item.IsPublished && !e.Product.Item.HasDeleted)
                .Where(e => e.Title == key || e.Description == key || e.Brief == key);

            if (fromPrice >= 0 && toPrice >= 0)
            {
                query = query.Where(e => (e.Product.Price >= fromPrice || e.Product.Sale >= fromPrice) && (e.Product.Price <= toPrice || e.Product.Sale <= toPrice));
            }

            var selected = query.OrderBy(e => e.Product.Item.Orders)
                .ThenByDescending(e => e.Product.Item.CreateDate)
                .Select(a => new ProductsDto
                {
                    ID = a.ProductId,
                    Title = a.Title,
                    ImageThumbName = a.Product.Image,
                    Description = a.Brief,
                    Price = a.Product.Price,
                    Sale = a.Product.Sale,
                    VoteNumber = a.Product.Item.ItemVote == null ? 1 : a.Product.Item.ItemVote.VoteNumber,
                    VoteRate = a.Product.Item.ItemVote == null ? 1 : a.Product.Item.ItemVote.VoteRate,
                });

            totalPage = selected.Count();
            if (Skip > 0) selected = selected.Skip(Skip);
            if (Take > 0) selected = selected.Take(Take);

            var data = selected.ToList();

            var imagePathThumb = string.Format(this._imageProductImagePath, companyId);
            foreach (var item in data)
            {
                item.ImageThumbName = this._url.VirtualPath(imagePathThumb + item.ImageThumbName);
            }

            return data;
        }

        public List<DataSimpleDto> GetDataSimple(int companyId, string languageId, int categoryId, bool inChildCat, out int totalPage, int Skip = 0, int Take = 0)
        {
            var query = this._productLanguageDAL.GetAll()
                .Where(e => e.Product.Item.CompanyId == companyId && e.LanguageId == languageId && e.Product.Item.IsPublished && !e.Product.Item.HasDeleted);
                
            if (categoryId > 0)
            {
                IList<int> listCategory;
                if (inChildCat)
                {
                    var categorys = this._categoryLanguageDAL.GetAllIncludeItem()
                        .Where(cat => cat.Category.Item.IsPublished && cat.LanguageId == languageId)
                        .Select(cat => new CategorySimpleDto
                        {
                            ID = cat.CategoryId,
                            Title = cat.Title,
                            ParentId = cat.Category.ParentId
                        }).ToList();

                    listCategory = this.GetAllChildId(categorys, categoryId);
                }
                else
                {
                    listCategory = new List<int>();
                    listCategory.Add(categoryId);
                }

                query = query.Where(c => listCategory.Contains(c.Product.CategoryId));
            }

            var selected = query.OrderBy(e => e.Product.Item.Orders)
                .ThenByDescending(e => e.Product.Item.CreateDate)
                .Select(a => new DataSimpleDto
                    {
                        Id = a.ProductId,
                        CategoryId = a.Product.CategoryId,
                        Title = a.Title,
                        Description = a.Brief,
                        ImagePath = a.Product.Image
                    });

            totalPage = selected.Count();
            if (Skip > 0) selected = selected.Skip(Skip);
            if (Take > 0) selected = selected.Take(Take);

            var data = selected.ToList();

            var imagePathThumb = string.Format(this._imageProductImagePath, companyId);
            foreach (var item in data)
            {
                item.ImagePath = this._url.VirtualPath(imagePathThumb + item.ImagePath);
            }

            return data;
        }

        public int GetCategoryIdByProductId(int companyId, int productId)
        {
            var query = this._productDAL.GetAll()
                .Where(e => e.Item.CompanyId == companyId && e.Id == productId)
                .Select( e => e.CategoryId);

            var data = query.FirstOrDefault();

            return data;
        }

        public IList<ProductCarDto> GetProductCars(int companyId, string languageId, out int totalPage, int skip = 0, int take = 0, int? manufacturerId = 0, int categoryId = 0, bool inChildCat = false, int ortherId = 0)
        {
            var query = this.QueryProduct(companyId, categoryId, inChildCat, ortherId, "", "", "", languageId, "");

            if (manufacturerId > 0) query = query.Where(e => e.Product.ProductCar.ManufacturerId == manufacturerId);

            var articles = query.Select(e => new ProductCarDto
            {
                Id = e.ProductId,
                Title = e.Title,
                ImageThumbName = e.Product.Image,
                Color = e.Product.Color,
                Price = e.Product.Price,
                PriceTypeId = e.Product.ProductCar == null ? 0 : e.Product.ProductCar.PriceType ?? 0,
                ManufacturerId =  e.Product.ProductCar == null ? 0 : e.Product.ProductCar.ManufacturerId,
                ManufacturerName = e.Product.ProductCar == null ? string.Empty : e.Product.ProductCar.ProductManufacturer.Name,
                ModelName = e.Product.ProductCar == null ? string.Empty : e.Product.ProductCar.ProductModel.Name,
                Province = e.Product.ProductCar == null ? string.Empty : e.Product.ProductCar.Province.Name,
                Type = e.Product.ProductCar == null ? string.Empty : e.Product.ProductCar.Type,
                CreateDate = e.Product.Item.CreateDate
            });

            totalPage = articles.Count();
            var r = articles.Skip(skip);
            if (take > 0) r = r.Take(take);

            var data = r.ToList();

            foreach (var dto in data)
            {
                dto.ImageThumbPath = this._url.VirtualPath(this._imageProductImagePath + dto.ImageThumbName);
                var time = DateTime.Now - dto.CreateDate;
                if (time.Days > 0) dto.Time = time.Days + " ngày";
                else if (time.Hours > 0) dto.Time = time.Hours + " giờ";
                else if (time.Minutes > 0) dto.Time = time.Minutes + " phút";

                if (dto.PriceTypeId > 0) dto.PriceTypeName = DataSource.DataSource.PriceTypeCollection.FirstOrDefault(e => e.Id == dto.PriceTypeId).Name;
            }

            return data;
        }

        public ProductCarInfoDto GetProductCar(int companyId, string languageId, int carId)
        {
            var query = this._productLanguageDAL.GetAll()
                .Where(e => e.Product.Item.IsPublished && e.Product.Item.CompanyId == companyId)
                .Where(e => e.ProductId == carId && e.LanguageId == languageId)
                .Select(e => new ProductCarInfoDto
            {
                TieuDe = e.Title,
                GiaBan = e.Product.Price,
                NamSanXuat = e.Product.ProductCar == null ? 0 : e.Product.ProductCar.InProduction ?? 0,
                SoKm = e.Product.ProductCar == null ? string.Empty : e.Product.ProductCar.EstimateKm,
                ConMoi = e.Product.ProductCar == null ? 100 : e.Product.ProductCar.RemainNew ?? 90,
                HopSo = e.Product.ProductCar == null ? string.Empty : e.Product.ProductCar.Gear,
                KieuDanDong = e.Product.ProductCar == null ? string.Empty : e.Product.ProductCar.DrivingStyle,
                NhienLieu = e.Product.ProductCar == null ? string.Empty : e.Product.ProductCar.Fuel,
                NgayDang = e.Product.Item.CreateDate,
                DiaChiLienHe = e.Product.ProductCar == null ? string.Empty : e.Product.ProductCar.ContactAddress,
                DienThoaiLienHe = e.Product.ProductCar == null ? string.Empty : e.Product.ProductCar.ContactTel,
                NguoiLienHe = e.Product.ProductCar == null ? string.Empty : e.Product.ProductCar.ContactMan,
                KhuVuc = e.Product.ProductCar == null ? string.Empty : e.Product.ProductCar.Province.Name,
                TienNghi = e.Product.ProductCar == null ? string.Empty : e.Product.ProductCar.Amenities,
                ThietBiAnToan = e.Product.ProductCar == null ? string.Empty : e.Product.ProductCar.SafetyEquipment,
                MoTa = e.Description
            });

            var dto = query.FirstOrDefault();

            if (dto != null)
            {
                var itemImage = this._productImageDAL.GetAll()
                    .Where(e => e.ItemId == carId)
                    .Select(e => e.ImageName);

                var images = itemImage.ToList();
                var thumbs = new List<string>();
                var details = new List<string>();

                var imageItemDetailPath = string.Format(this._imageItemDetailPath, companyId);
                var imageItemThumbPath = string.Format(this._imageItemThumbPath, companyId);
                foreach (var img in images)
                {
                    details.Add(this._url.VirtualPath(imageItemDetailPath + img));
                    thumbs.Add(this._url.VirtualPath(imageItemThumbPath + img));
                }

                dto.DanhSachHinhDetail = string.Join(",", details);
                dto.DanhSachHinhThumb = string.Join(",", thumbs);
            }

            return dto;
        }

        public IList<ProductInfoDto> GetList(int companyId, out int totalPage, int skip = 0, int take = 0, int? manufacturerId = 0, int? supplierId = 0, int categoryId = 0, bool inChildCat = false, int ortherId = 0, string colorId = "", string styleId = "", string typeId = "", string languageId = "vi-VN", string tag = "")
        {
            var query = this.QueryProduct(companyId, categoryId, inChildCat, ortherId, typeId, colorId, styleId, languageId, tag);

            var articles = query.Select(a => new ProductInfoDto
            {
                Id = a.ProductId,
                Title = a.Title,
                Brief = a.Brief,
                VoteNumber = a.Product.Item.ItemVote == null ? 0 : a.Product.Item.ItemVote.VoteNumber,
                VoteRate = a.Product.Item.ItemVote == null ? 0 : a.Product.Item.ItemVote.VoteRate,
                ImageThumbName = a.Product.Image,
                CategoryId = a.Product.CategoryId,
                Color = a.Product.Color,
                Style = a.Product.Style,
                Sale = a.Product.Sale,
                Price = a.Product.Price,
                Likes = a.Product.Item.ItemLike == null ? 0 : a.Product.Item.ItemLike.Likes,
                UnLikes = a.Product.Item.ItemLike == null ? 0 : a.Product.Item.ItemLike.UnLikes
            });

            totalPage = articles.Count();
            var r = articles.Skip(skip);
            if (take > 0) r = r.Take(take);

            var data = r.ToList();

            var imageProductThumbPath = string.Format(this._imageProductImagePath, companyId);
            data.ForEach(dto => dto.ImageThumbPath = this._url.VirtualPath(imageProductThumbPath + dto.ImageThumbName));

            return data;
        }

        public IList<DataSimpleDto> GetSimpleByType(int companyId, int categoryId, bool inChildCat = false, int ortherId = 0, string typeId = "", string languageId = "vi-VN")
        {
            var query =
                this._productLanguageDAL.GetAllIncludes()
                .Where(c => c.LanguageId == languageId)
                .Where(c => c.Product.Item.IsPublished && !c.Product.Item.HasDeleted && c.Product.Item.CompanyId == companyId);

            if (ortherId > 0)
            {
                if (categoryId == 0)
                    categoryId = this._productDAL.GetAll()
                        .Where(o => o.Id == ortherId)
                        .Select(o => o.CategoryId).FirstOrDefault();

                query = query.Where(language => language.ProductId != ortherId);
            }

            if (!string.IsNullOrEmpty(typeId))
            {
                var arrType = typeId.Split(',');
                query = arrType.Aggregate(query, (current, type) => current.Where(c => c.Product.Type.Contains(type)));
            }

            if (categoryId > 0)
            {
                IList<int> listCategory;
                if (inChildCat)
                {
                    var categorys = this._categoryLanguageDAL.GetAllIncludeItem()
                        .Where(cat => cat.Category.Item.IsPublished && cat.LanguageId == languageId)
                        .Select(cat => new CategorySimpleDto
                        {
                            ID = cat.CategoryId,
                            Title = cat.Title,
                            ParentId = cat.Category.ParentId
                        }).ToList();

                    listCategory = this.GetAllChildId(categorys, categoryId);

                }
                else listCategory = new List<int>();

                listCategory.Add(categoryId);
                query = query.Where(c => listCategory.Contains(c.Product.CategoryId));
            }

            query = query.OrderBy(o => o.Product.Item.Orders);

            var products = query.Select(a => new DataSimpleDto
            {
                Id = a.ProductId,
                Title = a.Title,
                ImagePath = a.Product.Image,
                Description = a.Description,
            });

            var data = products.ToList();

            var imageProductThumbPath = string.Format(this._imageProductImagePath, companyId);
            data.ForEach(dto => dto.ImagePath = this._url.VirtualPath(imageProductThumbPath + dto.ImagePath));

            return data;
        }

        public IList<DataSimpleDto> GetListSimple(int companyId, out int totalPage, int skip = 0, int take = 0, int? manufacturerId = 0, int? supplierId = 0, int categoryId = 0, bool inChildCat = false, int ortherId = 0, string colorId = "", string styleId = "", string typeId = "", string languageId = "vi-VN", string tag = "")
        {
            var query = this.QueryProduct(companyId, categoryId, inChildCat, ortherId, typeId, colorId, styleId, languageId, tag);

            var articles = query.Select(a => new DataSimpleDto
            {
                Id = a.ProductId,
                Title = a.Title,
                ImagePath = a.Product.Image,
                Description = a.Description,
            });

            totalPage = articles.Count();
            var r = articles.Skip(skip);
            if (take > 0) r = r.Take(take);

            var data = r.ToList();

            var imageProductThumbPath = string.Format(this._imageProductImagePath, companyId);
            data.ForEach(dto => dto.ImagePath = this._url.VirtualPath(imageProductThumbPath + dto.ImagePath));

            return data;
        }

        public IList<ProductWithImagePriceDto> GetListProductWithImageAndPrice(int companyId, out int totalPage, int skip = 0, int take = 0, int? manufacturerId = 0, int? supplierId = 0, int categoryId = 0, bool inChildCat = false, int ortherId = 0, string colorId = "", string styleId = "", string typeId = "", string languageId = "vi-VN", string tag = "")
        {
            var query = this.QueryProduct(companyId, categoryId, inChildCat, ortherId, typeId, colorId, styleId, languageId, tag);

            var articles = query.Select(a => new ProductWithImagePriceDto
            {
                ID = a.ProductId,
                Title = a.Title,
                ImageThumbName = a.Product.Image,
                Description = a.Description,
                Price = a.Product.Price,
                Sale = a.Product.Sale
            });

            totalPage = articles.Count();
            var r = articles.Skip(skip);
            if (take > 0) r = r.Take(take);

            var data = r.ToList();

            var imageProductThumbPath = string.Format(this._imageProductImagePath, companyId);
            data.ForEach(dto => dto.ImageThumdPath = this._url.VirtualPath(imageProductThumbPath + dto.ImageThumbName));

            return data;
        }

        public IList<ProductsDto> GetListProductWithImageAndPriceAndVote(int companyId, out int totalPage, int skip = 0, int take = 0, int? manufacturerId = 0, int? supplierId = 0, int categoryId = 0, bool inChildCat = false, int ortherId = 0, string colorId = "", string styleId = "", string typeId = "", string languageId = "vi-VN", string tag = "")
        {
            var query = this.QueryProduct(companyId, categoryId, inChildCat, ortherId, typeId, colorId, styleId, languageId, tag);

            var products = query.Select(a => new ProductsDto
            {
                ID = a.ProductId,
                Title = a.Title,
                ImageThumbName = a.Product.Image,
                Description = a.Brief,
                Price = a.Product.Price,
                Sale = a.Product.Sale,
                VoteNumber = a.Product.Item.ItemVote == null ? 1 : a.Product.Item.ItemVote.VoteNumber,
                VoteRate = a.Product.Item.ItemVote == null ? 1 : a.Product.Item.ItemVote.VoteRate,
                ViewNumber = a.Product.Item.ItemView == null ? 1 : a.Product.Item.ItemView.Views,

                // luu tam code
                ImageThumdPath = a.Product.Code
            });

            totalPage = products.Count();
            var r = products.Skip(skip);
            if (take > 0) r = r.Take(take);

            var data = r.ToList();

            var imageProductThumbPath = string.Format(this._imageProductImagePath, companyId);
            foreach (var dto in data)
            {
                var id = dto.ID.ToString();
                dto.PayNumber = this._orderProductDAL.GetAll().Where(e => e.Order.CompanyId == companyId && !e.Order.IsDeleted && (e.ProductCode == id || e.ProductCode == dto.ImageThumdPath)).Select(e => e.Quality).DefaultIfEmpty(0).Sum();
                dto.ImageThumdPath = this._url.VirtualPath(imageProductThumbPath + dto.ImageThumbName);
            }

            return data;
        }

        public IList<ProductsDto> GetListProductTheSameCategory(int productId, int companyId, out int totalPage, int skip = 0, int take = 0, string languageId = "vi-VN", string same = "")
        {
            var product = this._productDAL.Get(e => e.Id == productId);
            if (product == null)
            {
                totalPage = 0;
                return new List<ProductsDto>();
            }

            var categoryId = 0;
            string colorId = "", styleId = "", typeId = "", tag = "";
            switch (same)
            {
                case "categoty":
                    categoryId = product.CategoryId;
                    break;
                case "type":
                    typeId = product.Type;
                    break;
                case "color":
                    colorId = product.Color;
                    break;
                case "style":
                    styleId = product.Style;
                    break;
                case "tag":
                    tag = product.Tag;
                    break;
            }

            var query = this.QueryProduct(companyId, categoryId, false, productId, typeId, colorId, styleId, languageId, tag);

            var articles = query.Select(a => new ProductsDto
            {
                ID = a.ProductId,
                Title = a.Title,
                ImageThumbName = a.Product.Image,
                Description = a.Description,
                Price = a.Product.Price,
                Sale = a.Product.Sale,
                VoteNumber = a.Product.Item.ItemVote == null ? 1 : a.Product.Item.ItemVote.VoteNumber,
                VoteRate = a.Product.Item.ItemVote == null ? 1 : a.Product.Item.ItemVote.VoteRate,
            });

            totalPage = articles.Count();
            var r = articles.Skip(skip);
            if (take > 0) r = r.Take(take);

            var data = r.ToList();

            var imageProductThumbPath = string.Format(this._imageProductImagePath, companyId);
            data.ForEach(dto => dto.ImageThumdPath = this._url.VirtualPath(imageProductThumbPath + dto.ImageThumbName));

            return data;
        }

        public DataSimpleDto GetDataSingle(int companyId, string languageId, int id)
        {
            var query = this._productLanguageDAL.GetAll()
                .Where(e => e.Product.Item.CompanyId == companyId && e.LanguageId == languageId && e.Product.Item.IsPublished && !e.Product.Item.HasDeleted && e.ProductId == id);

            var selected = query.Select(a => new DataSimpleDto
                {
                    Id = a.ProductId,
                    CategoryId = a.Product.CategoryId,
                    Title = a.Title,
                    Description = a.Brief,
                    ImagePath = a.Product.Image
                });

            var data = selected.FirstOrDefault();

            if (data != null && !string.IsNullOrEmpty(data.ImagePath))
            {
                var imagePathThumb = string.Format(this._imageProductImagePath, companyId);
                data.ImagePath = this._url.VirtualPath(imagePathThumb + data.ImagePath);
            }

            return data;
        }

        public ProductDetailDto GetProductById(int id, string language, int companyId)
        {
            var query = this._productLanguageDAL.GetAllIncludeViewImage()
                .Where(c => c.ProductId == id && c.LanguageId == language && c.Product.Item.HasDeleted == false && c.Product.Item.IsPublished && c.Product.Item.CompanyId == companyId)
                .OrderBy(a => a.Product.Item.Orders)
                .Select(o => new ProductDetailDto
                {
                    Id = o.ProductId,
                    CategoryId = o.Product.CategoryId,
                    Code = o.Product.Code,
                    Tag = o.Product.Tag,
                    Type = o.Product.Type,

                    Title = o.Title,
                    Brief = o.Brief,
                    Description = o.Description,

                    ImageThumbName = o.Product.Image,
                    ImageDetailNames = o.Product.Item.ItemImages.Select(image => image.ImageName),

                    Likes = o.Product.Item.ItemLike == null ? 0 : o.Product.Item.ItemLike.Likes,
                    UnLikes = o.Product.Item.ItemLike == null ? 0 : o.Product.Item.ItemLike.UnLikes,
                    Views = o.Product.Item.ItemView == null ? 0 : o.Product.Item.ItemView.Views,
                    Color = o.Product.Color,
                    Style = o.Product.Style,
                    Sale = o.Product.Sale,
                    Price = o.Product.Price,

                    VoteNumber = o.Product.Item.ItemVote == null ? 1 : o.Product.Item.ItemVote.VoteNumber,
                    VoteRate = o.Product.Item.ItemVote == null ? 1 : o.Product.Item.ItemVote.VoteRate,
                });

            var data = query.FirstOrDefault();

            // update path image
            if (data != null)
            {
                var imageProductThumbPath = string.Format(this._imageProductImagePath, companyId);
                data.ImageThumdPath = this._url.VirtualPath(imageProductThumbPath + data.ImageThumbName);

                var imageProductDetailPath = string.Format(this._imageItemDetailPath, companyId);

                data.ImageDetailPaths = new List<string>();
                foreach (var name in data.ImageDetailNames)
                {
                    var path = this._url.VirtualPath(imageProductDetailPath + name);
                    data.ImageDetailPaths.Add(path);
                }

                data.Description = data.Description.PageArticleCommand("Xem thêm");
            }

            return data;
        }
        
        public GioHangDto GetProductCartsById(int id, string language, int companyId)
        {
            var query = this._productLanguageDAL.GetAllIncludeViewImage()
                .Where(c => c.ProductId == id && c.LanguageId == language && c.Product.Item.HasDeleted == false && c.Product.Item.IsPublished && c.Product.Item.CompanyId == companyId)
                .OrderBy(a => a.Product.Item.Orders)
                .Select(o => new GioHangDto
                {
                    ProductID = o.ProductId,
                    ProductCode = o.Product.Code,
                    ProductName = o.Title,
                    Image = o.Product.Image,
                    UnitPrice = o.Product.Sale == null || o.Product.Sale == 0 ? o.Product.Price ?? 0 : o.Product.Sale ?? 0
                });

            var data = query.FirstOrDefault();

            // update path image
            if (data != null)
            {
                var imageProductThumbPath = string.Format(this._imageProductImagePath, companyId);
                data.Image = this._url.VirtualPath(imageProductThumbPath + data.Image);
            }

            return data;
        }

        public List<TypeDto> GetTypes(int companyId)
        {
            var query = this._productTypeDAL.GetAll().Where(e => e.CompanyId == companyId)
                .Select(e => new TypeDto
                {
                    Code = e.Id,
                    Name = e.Description
                });

            var data = query.ToList();

            return data;
        }

        public List<ProductPriceDto> GetPrices(List<int> productIds)
        {
            var query = this._productPriceDAL.GetAll().Where(e => productIds.Contains(e.ProductId))
                .Select(e => new ProductPriceDto
                {
                    ProductId = e.ProductId,
                    Price = e.Price,
                    Quatity = e.Quantity
                });

            var data = query.ToList();

            return data;
        }

        public bool InsertProductImage(int productId, string imageName)
        {
            try
            {
                var objProduct = new ItemImage {ItemId = productId, ImageName = imageName};

                _productImageDAL.Add(objProduct);
                SaveChanges();
                return true;
            }
            catch(Exception)
            {
                return false;
            }
        }

        public void Order(
            int companyId,
            string host, 
            bool enableSSL, 
            string account, 
            string password, 
            string mailTo,
            int port, 
            string subject, 
            string body,
            string customerName,
            string customerEmail,
            string customerAddress,
            string customerPhone,
            string note,
            string method,
            string delivery,
            List<GioHangDto> giohang)
        {
            giohang = giohang.Where(e => e.Quantity > 0).ToList();

            try
            {
                MailManager mail = new MailManager();
                mail.EnableSSL = enableSSL;
                mail.Host = host;
                mail.Port = port;
                mail.From = account;
                mail.Password = password;
                mail.To = customerEmail + ";" + mailTo;
                mail.Title = subject;
                mail.Content = body;
                mail.SendEmail();
            }
            catch (Exception ex)
            {
                throw new BusinessLogicLayerException("Lỗi Email: " + ex.Message);
            }

            var od = new Entity.Order();
            od.CompanyId = companyId;
            od.CreateDate = DateTime.Now;
            od.CustomerAddress = customerAddress;
            od.CustomerEmail = customerEmail;
            od.CustomerName = customerName;
            od.CustomerPhone = customerPhone;
            od.Note = note;
            od.Delivery = delivery;
            od.Method = method;
            od.Due = giohang.Sum(e => e.TotalCost);

            foreach (var hang in giohang)
            {
                var p = new OrderProduct();
                p.ProductCode = string.IsNullOrEmpty(hang.ProductCode) ? hang.ProductID.ToString() : hang.ProductCode;
                p.ImagePath = hang.Image;
                p.PriceUnit = hang.UnitPrice;
                p.ProductName = hang.ProductName;
                p.Quality = hang.Quantity;
                od.OrderProducts.Add(p);
            }

            this._orderDAL.Add(od);
            this.SaveChanges();
        }
        #endregion

        #region manufacturer
        public ManufacturerDto GetManufacturerById(int companyId, int manufacturerId)
        {
            var query = this._manufacturerDAL.GetAll()
                .Where(e => e.Id == manufacturerId && e.Item.CompanyId == companyId)
                .Select(e => new ManufacturerDto
                    {
                        ID = e.Id,
                        Title = e.Name,
                        CategoryId = e.CategoryId
                    });

            return query.FirstOrDefault();
        }

        /// <summary>
        /// Danh mục và đếm sản phẩm từng danh mục
        /// </summary>
        /// <param name="companyId">Mã công ty</param>
        /// <param name="categoryId">The parent Id.</param>
        /// <param name="productId">The product Id </param>
        /// <param name="manufacturerId">neu co manufacturerId thi lay category tu manufacturer nay </param>
        /// <param name="hasParent">co lay luon hang san xuat cua danh muc cha ko</param>
        /// <param name="hasChild">co lay luon hang san xuat cua danh muc con ko</param>
        /// <returns>
        /// List category
        /// </returns>
        public IList<ManufacturerCountDto> GetManufacturerCountProduct(int companyId, int categoryId, int productId = 0, int manufacturerId = 0, bool hasParent = true, bool hasChild = true)
        {
            var data = new List<ManufacturerCountDto>();

            if (manufacturerId > 0)
            {
                categoryId = this._manufacturerDAL.GetAll()
                    .Where(e => e.Id == manufacturerId)
                    .Select(e => e.CategoryId)
                    .FirstOrDefault();
            }
            else if (productId > 0)
            {
                categoryId = this._productDAL.GetAll()
                    .Where(e => e.Id == productId)
                    .Select(e => e.CategoryId)
                    .FirstOrDefault();
            }

            var manufacturers = this.GetManufacturerCountProductByCategory(companyId, categoryId);
            data.AddRange(manufacturers);

            if (hasParent)
            {
                var category = this._categoryDAL.GetAll().FirstOrDefault(o => o.Id == categoryId && o.Item.CompanyId == companyId);
                if (category != null)
                {
                    var catId = category.ParentId ?? 0;

                    while (catId != 0)
                    {
                        manufacturers = this.GetManufacturerCountProductByCategory(companyId, catId);
                        data.AddRange(manufacturers);

                        category = this._categoryDAL.GetAll().FirstOrDefault(o => o.Id == catId && o.Item.CompanyId == companyId);
                        catId = category.ParentId ?? 0;
                    }
                }
            }

            if (hasChild)
            {
                var categorys = this._categoryDAL.GetAll()
                        .Where(cat => cat.Item.IsPublished)
                        .Select(cat => new CategorySimpleDto
                        {
                            ID = cat.Id,
                            ParentId = cat.ParentId
                        }).ToList();

                var listCategory = this.GetAllChildId(categorys, categoryId);
                foreach (var id in listCategory)
                {
                    manufacturers = this.GetManufacturerCountProductByCategory(companyId, id);
                    data.AddRange(manufacturers);
                }
            }

            return data;
        }
        #endregion

        #region Private method
        private IList<ManufacturerCountDto> GetManufacturerCountProductByCategory(int companyId, int categoryId)
        {
            var catQuery = this._manufacturerDAL.GetAll()
                .Where(e => e.Item.IsPublished && e.Item.CompanyId == companyId)
                .Where(e => e.CategoryId == categoryId);

            var dtoQuery = catQuery.Select(o => new ManufacturerCountDto
            {
                ID = o.Id,
                Name = o.Name,
                Count = o.ProductCars.Count(e => e.Product.Item.IsPublished && e.Product.Item.CompanyId == companyId)
            });

            var data = dtoQuery.ToList();

            return data;
        }

        private IQueryable<ProductLanguage> QueryProduct(
            int companyId,
            int categoryId,
            bool inChildCat,
            int ortherId,
            string typeId,
            string colors,
            string styles,
            string languageId,
            string tag)
        {
            var query =
                this._productLanguageDAL.GetAllIncludes()
                .Where(c => c.LanguageId == languageId)
                .Where(c => c.Product.Item.IsPublished)
                .Where(c => !c.Product.Item.HasDeleted)
                .Where(c => c.Product.Item.CompanyId == companyId);

            if (ortherId > 0)
            {
                if (categoryId == 0)
                    categoryId = this._productDAL.GetAll()
                        .Where(o => o.Id == ortherId)
                        .Select(o => o.CategoryId).FirstOrDefault();

                query = query.Where(language => language.ProductId != ortherId);
            }

            if (!string.IsNullOrEmpty(tag))
            {
                query = query.Where(language => language.Product.Tag.Contains(tag));
            }

            if (!string.IsNullOrEmpty(typeId))
            {
                var arrType = typeId.Split(',');
                query = arrType.Aggregate(query, (current, type) => current.Where(c => c.Product.Type.Contains(type)));
               
            }

            if (!string.IsNullOrEmpty(colors))
            {
                var arrColor = colors.Split(',');
                //query = arrColor.Aggregate(query, (current, color) => current.Where(c => c.Product.Color.Contains(color)));
                var data = query.ToList();
                data = data.Where(obj => obj.Product.Color != null && obj.Product.Color.Split(',').Join(arrColor, productStyle => productStyle, style => style, (productStyle, style) => productStyle).Count() > 0)
                    .ToList();
                query = data.AsQueryable();
            }

            if (!string.IsNullOrEmpty(styles))
            {
                var arrStyle = styles.Split(',');
                //query = arrStyle.Aggregate(query, (current, style) => current.Where(c => c.Product.Style.Contains(style)));
                var data = query.ToList();
                data = data.Where(obj => obj.Product.Style != null && obj.Product.Style.Split(',').Join(arrStyle, productStyle => productStyle, style => style, (productStyle, style) => productStyle).Count() > 0)
                    .ToList();
                query = data.AsQueryable();
            }

            if (categoryId > 0)
            {
                IList<int> listCategory;
                if (inChildCat)
                {
                    var categorys = this._categoryLanguageDAL.GetAll()
                        .Where(cat => cat.Category.Item.IsPublished && cat.LanguageId == languageId && cat.Category.Item.CompanyId == companyId)
                        .Select(cat => new CategorySimpleDto
                            {
                                ID = cat.CategoryId, 
                                Title = cat.Title, 
                                ParentId = cat.Category.ParentId
                            }).ToList();

                    listCategory = this.GetAllChildId(categorys, categoryId);

                }
                else listCategory = new List<int>();

                listCategory.Add(categoryId);
                query = query.Where(c => listCategory.Contains(c.Product.CategoryId));
            }

            query = query.OrderBy(o => o.Product.Item.Orders).ThenByDescending(e => e.ProductId);

            return query;
        }

        private IList<int> GetAllChildId(IList<CategorySimpleDto> category, int? parentId)
        {
            var subcats = category.Where(o => o.ParentId == parentId).ToList(); // lay tat ca con cua parentID

            var result = new List<int>();
            foreach (var subcat in subcats)
            {
                if (subcat != null)
                {
                    var temp = this.GetAllChildId(category, subcat.ID);

                    result.Add(subcat.ID);
                    if (temp != null && temp.Count > 0)
                    {
                        result.AddRange(temp);
                    }
                }
            }

            return result;
        }
        #endregion
    }
}
